import torch
import numpy as np
import math
from  sseHp import Hyperparameter
hp = Hyperparameter()
import sys  # 导入sys模块
sys.setrecursionlimit(10000)  # 将默认的递归深度修改为3000

class Creator:
    # def __init__(self):
    #     pass
    # def data_create(self):
    #     Items = []
    #     # np.random.seed(0) # 随机固定
    #     # 数据生成变成了12000
    # # torch.manual_seed(1)
    #     for i in range(12000):#12000
    #         if i<1800:#180
    #             x,y,z = 4.,4.,3.
    #         elif i<3600:#360
    #             x,y,z = 6.,4.,3.
    #         elif i<5400:#540
    #             x,y,z = 6.,3.,3.
    #         elif i<7200:#720
    #             x,y,z = 6.,3.,2.
    #         elif i<9000:#900
    #             x,y,z = 4.,3.,2.
    #         elif i<10800:#1080
    #             x,y,z = 4.,3.,3.
    #         elif i<12000:#1200
    #             x,y,z = 4.,2.,2. # 4,2,2
    #         Items.append([i, x, y, z])
    #     Items_noindex = list(Items.copy())
    #     Items_noindex = np.array(Items_noindex)
    #     Items_noindex = Items_noindex[:, 1:] # 原1:-1
    #     Items_noindex = torch.tensor(Items_noindex)
    #     Items_noindex = Items_noindex.unsqueeze(1)
    #     return Items_noindex
    #   shape[1200,1,3] batch,emb,length
    # def data_create_random_profit(self):
    #     Items = []
    #     size = hp.TOTAL_ITEMS_SUM
    #     for i in range(size): #
    #         t=np.random.randint(20,150)
    #         if i< 0.15 * size:
    #             x,y,z = 4.,4.,3.
    #         elif i<0.3 * size:
    #             x,y,z = 6.,4.,3.
    #         elif i<0.45 * size:
    #             x,y,z = 6.,3.,3.
    #         elif i<0.6 * size:
    #             x,y,z = 6.,3.,2.
    #         elif i<0.75 * size:
    #             x,y,z = 4.,3.,2.
    #         elif i<0.9 * size:
    #             x,y,z = 4.,3.,3.
    #         elif i<size:
    #             x,y,z = 4.,2.,2.
    #         Items.append([i, x, y, z, t])
    #     Items_noindex = list(Items.copy())
    #     Items_noindex = np.array(Items_noindex)
    #     Items_noindex = Items_noindex[:, 1:] # 原1:-1
    #     Items_noindex = torch.tensor(Items_noindex)
    #     Items_noindex = Items_noindex.unsqueeze(1)
    #     return Items_noindex

    # def data_create_random_profit_asu(self):
    #     Items = []
    #     size = hp.TOTAL_ITEMS_SUM
    #     for i in range(size):  #
    #         if i < 0.15 * size:
    #             x, y, z = 4., 4., 3.
    #         elif i < 0.3 * size:
    #             x, y, z = 6., 4., 3.
    #         elif i < 0.45 * size:
    #             x, y, z = 6., 3., 3.
    #         elif i < 0.6 * size:
    #             x, y, z = 6., 3., 2.
    #         elif i < 0.75 * size:
    #             x, y, z = 4., 3., 2.
    #         elif i < 0.9 * size:
    #             x, y, z = 4., 3., 3.
    #         elif i < size:
    #             x, y, z = 4., 2., 2.
    #         Items.append([i, x, y, z])
    #     Items_noindex = list(Items.copy())
    #     Items_noindex = np.array(Items_noindex)
    #     Items_noindex = Items_noindex[:, 1:]  # 原1:-1
    #     Items_noindex = torch.tensor(Items_noindex)
    #     Items_noindex = Items_noindex.unsqueeze(1)
    #     return Items_noindex

    # def data_creat_save(self):
    #     bins=self.data_create()
    #     torch. save(bins,'goods_data.pt')
    # def data_creat_save_random_profit(self):
    #     bins=self.data_create_random_profit()
    #     torch. save(bins,'goods_data_random_profit.pt')
    # def data_creat_save_random_profit_asu(self):
    #     bins=self.data_create_random_profit()
    #     torch. save(bins,'goods_data_random_profit_asu.pt')
    # def data_create_profit_actual(self):
    #     Items = []
    #     size = hp.TOTAL_ITEMS_SUM
    #     for i in range(size): #
    #         if i < 0.1 * size:
    #             x,y,z,t = 4.,3.,3.,5. # 5
    #         elif i < 0.1 * size:
    #             x,y,z,t = 3.,3.,3.,5. # 5
    #         elif i < 0.1 * size:
    #             x,y,z,t = 3.,3.,2.,5. # 5
    #         elif i < size:
    #             x,y,z,t = 3.,2.,2.,5. # 5
    #         Items.append([i, x, y, z, t])
    #     Items_noindex = list(Items.copy())
    #     Items_noindex = np.array(Items_noindex)
    #     Items_noindex = Items_noindex[:, 1:]  # 原1:-1
    #     Items_noindex = torch.tensor(Items_noindex)
    #     Items_noindex = Items_noindex.unsqueeze(1)
    #     return Items_noindex

    def data_creat_save_profit_actual(self):
        bins = self.data_create_profit_actual()
        torch.save(bins, 'goods_data_profit_actual_Task15.pt')
    def data_create_profit_actual(self):
        Items = []
        size = hp.TOTAL_ITEMS_SUM
        for i in range(18000): #
            tt = float(torch.round(torch.tensor(np.random.random_sample(1)), decimals=4))
            if i < 2000:#200
                t = tt * 10. + 90. #50-60
                x, y, z, t, family = 4., 3., 3., t, 1
                Items.append([i, x, y, z, t, family])
            elif i < 6000: #
                t = tt * 10. + 80. #40-50
                x, y, z, t, family = 3., 3., 3., t, 2
                Items.append([i, x, y, z, t, family])
            elif i < 11000: #
                t = tt * 10. + 70. #30-40
                x, y, z, t, family = 3., 3., 2., t, 3
                Items.append([i, x, y, z, t, family])
            elif i < 18000:#1800
                t = tt * 10. + 50. #20-30
                x, y, z, t, family = 3., 2., 2., t, 4
                Items.append([i, x, y, z, t, family])
            # elif i < 900:#1800
            #     t = tt * 10. + 40. #20-30
            #     x, y, z, t, family = 3., 2., 1., t, 5
            #     Items.append([i, x, y, z, t, family])
            # elif i < 1080:#1800
            #     t = tt * 10. + 30. #20-30
            #     x, y, z, t, family = 4., 3., 2., t, 6
            #     Items.append([i, x, y, z, t, family])
            # elif i < 1200:#1800
            #     t = tt * 10. + 20. #20-30
            #     x, y, z, t, family = 5., 5., 6., t, 7
            #     Items.append([i, x, y, z, t, family])
        Items_noindex = list(Items.copy())
        Items_noindex = np.array(Items_noindex)
        Items_noindex = Items_noindex[:, :]  # 原1:-1
        Items_noindex = torch.tensor(Items_noindex)
        Items_noindex = Items_noindex.unsqueeze(1)
        return Items_noindex

    def data_creat_save_profit_actual_little(self):
        bins = self.data_create_profit_actual_little()
        torch.save(bins, 'goods_data_profit_actual_little_2.pt')
    def data_create_profit_actual_little(self):
        Items = []
        size = 188
        for i in range(size): #
            tt = float(torch.round(torch.tensor(np.random.random_sample(1)), decimals=4))
            if i < 20:#200
                t = tt * 10. + 50. #50-60
                x, y, z, t, family = 6., 7., 8., t, 1
                Items.append([i, x, y, z, t, family])
            elif i < 40: #
                t = tt * 10. + 40. #40-50
                x, y, z, t, family = 4., 5., 6., t, 2
                Items.append([i, x, y, z, t, family])
            elif i < 60: #
                t = tt * 10. + 30. #30-40
                x, y, z, t, family = 2., 2., 2., t, 3
                Items.append([i, x, y, z, t, family])
            elif i < 188:#1800
                t = tt * 10. + 20. #20-30
                x, y, z, t, family = 3., 4., 5., t, 4
                Items.append([i, x, y, z, t, family])
        Items_noindex = list(Items.copy())
        Items_noindex = np.array(Items_noindex)
        Items_noindex = Items_noindex[:, :]  # 原1:-1
        Items_noindex = torch.tensor(Items_noindex)
        Items_noindex = Items_noindex.unsqueeze(1)
        return Items_noindex

    # def data_create_profit_actual(self):
    #     Items = []

    #     size = hp.TOTAL_ITEMS_SUM
    #     for i in range(size): #
    #         # t = np.random.randint(20.,100.)
    #         if i < 100:#200
    #             t = float(np.random.random_sample(1)) * 10. + 40. #50-60
    #             x, y, z, t, family = 4., 4., 4., t, 1
    #             Items.append([i, x, y, z, t, family])
    #         elif i < 200:
    #             t = float(np.random.random_sample(1)) * 10. + 30. #40-50
    #             x, y, z, t, family = 4., 4., 3.5, t, 2
    #             Items.append([i, x, y, z, t, family])
    #         elif i < 300:
    #             t = float(np.random.random_sample(1)) * 10. + 20. #30-40
    #             x, y, z, t, family = 4., 4., 3., t, 3
    #             Items.append([i, x, y, z, t, family])
    #         elif i < 592:
    #             t = float(np.random.random_sample(1)) * 10. + 10. #20-30
    #             x, y, z, t, family = 4., 3.5, 3., t, 4
    #             Items.append([i, x, y, z, t, family])
    #     Items_noindex = list(Items.copy())
    #     Items_noindex = np.array(Items_noindex)
    #     Items_noindex = Items_noindex[:, :]  # 原1:-1
    #     Items_noindex = torch.tensor(Items_noindex)
    #     Items_noindex = Items_noindex.unsqueeze(1)
    #     return Items_noindex

    # def data_creat_save_random_profit_actual(self):
    #     bins = self.data_create_profit_actual()
    #     torch.save(bins, 'goods_data_random_profit_actual.pt')

    # def data_create_all_random_actual(self):
    #     Items = []
    #     size = hp.TOTAL_ITEMS_SUM
    #     for i in range(size):  #
    #         # t = np.random.randint(20.,100.)
    #         if i < 300:  # 200
    #             t = float(np.random.random_sample(1)) * 10. + 50.
    #             l = float(np.random.random_sample(1)) + 3.
    #             w = float(np.random.random_sample(1)) + 2.
    #             h = float(np.random.random_sample(1)) + 2.
    #             # 50-60
    #             family = 1
    #             Items.append([i, l, w, h, t, family])
    #         elif i < 700:
    #             t = float(np.random.random_sample(1)) * 10. + 40.  # 40-50
    #             l = float(np.random.random_sample(1)) + 2.
    #             w = float(np.random.random_sample(1)) +2.
    #             h = float(np.random.random_sample(1)) +2.
    #             family = 2
    #             Items.append([i, l, w, h, t, family])
    #         elif i < 1300:
    #             t = float(np.random.random_sample(1)) * 10. + 30.  # 30-40
    #             l = float(np.random.random_sample(1)) +2.
    #             w = float(np.random.random_sample(1)) +1.
    #             h = float(np.random.random_sample(1)) +1.
    #             family = 3
    #             Items.append([i, l, w, h, t, family])
    #         elif i < 2400:
    #             t = float(np.random.random_sample(1)) * 10. + 20.  # 20-30
    #             l = float(np.random.random_sample(1)) +2.
    #             w = float(np.random.random_sample(1)) +1.
    #             h = float(np.random.random_sample(1)) +1.
    #             family = 4
    #             Items.append([i, l, w, h, t, family])
    #     Items_noindex = list(Items.copy())
    #     Items_noindex = np.array(Items_noindex)
    #     Items_noindex = Items_noindex[:, 1:]  # 原1:-1
    #     Items_noindex = torch.tensor(Items_noindex)
    #     Items_noindex = Items_noindex.unsqueeze(1)
    #     return Items_noindex
    #
    # def data_creat_save_random_profit_actual(self):
    #     bins = self.data_create_random_profit_actual()
    #     torch.save(bins, 'goods_data_random_profit_actual.pt')

    # 只为强化学习算法而生
    def bin_create(self, item_list, index_list): # item 为array,为得出的序列
        item_data = []
        for i in range(len(item_list)):
            index = index_list[i][0]
            item = Bin('0', item_list[index][1], item_list[index][2], item_list[index][3], item_list[index][4], 0, item_list[index][5]) #货物的0长1宽2高和3价值
            item_data.append(item)
        return item_data

    def bin_create_num(self, item_list, index_list): # item 为array,为得出的序列
        # 装载成为物品的顺序 num表示有货物初始编号
        item_data = []
        print(len(item_list))
        for i in range(len(item_list)):
            # print(i)
            index = index_list[i][0]
            item = Bin(item_list[index][0], item_list[index][1], item_list[index][2], item_list[index][3], item_list[index][4], 0, item_list[index][5]) #货物的0长1宽2高和3价值
            item_data.append(item)
        return item_data

    def car_list_create(self):
        car2 = Car('3DBin_20', 20, 20, 20, 3000, Attr.Position, 0)
        car0 = Car('3DBin_12', 12, 12, 12, 3000, Attr.Position, 0)
        car1 = Car('3DBin_16', 16, 16, 16, 3000, Attr.Position, 0)
        #car3 = Car('3DBin_24', 24, 24, 24, 3000, Attr.Position, 0)
        #car3 = Car('3DBin_30', 30, 30, 30, 3000, Attr.Position, 0)
        car3 = Car('3DBin_actual', 42, 16, 18, 3000, Attr.Position, 0) #长度单位：公分；3000表示载重3000千克

        # car4 = Car('3t货车', 25, 25, 25, 3000, Attr.Position, 0)
        # car5 = Car('3t货车', 26, 26, 26, 3000, Attr.Position, 0)
        # car6 = Car('3t货车', 27, 27, 27, 3000, Attr.Position, 0)
        # car7 = Car('3t货车', 28, 28, 28, 3000, Attr.Position, 0)
        # car8 = Car('3t货车', 29, 29, 29, 3000, Attr.Position, 0)
        # car9 = Car('3t货车', 30, 30, 30, 3000, Attr.Position, 0)
        # car10 = Car('3t货车', 31, 31, 31, 3000, Attr.Position, 0)
        # car11 = Car('3t货车', 32, 32, 32, 3000, Attr.Position, 0)
        car_list20 = [car2]
        car_list12 = [car0]
        car_list16 = [car1]
        car_list24 = [car3]
        return car_list12,car_list16,car_list20,car_list24
        # car_list25 = [car4]
        # car_list26 = [car5]
        # car_list27 = [car6]
        # car_list28 = [car7]
        # carlist29 = [car8]
        # car_list3_0 = [car9]
        # car_list31 = [car10]
        # car_list32 = [car11]
    #************************  此方法需要重写 ******************
    # 功能设想：将多种启发式算法的结果作为列表输入，可以是所有大小类型的货箱的实验结果，得到每种货箱的均值或者中位数作为baseline
    def baseline_b(self,np_num):
        sum = 0
        for i in np_num:
            sum += i
        return float(format(sum / len(np_num), '.7f'))
    # b_12 = 0.6  # baseline_b(bin_12_16_20_24[0,:])
    # b_16 = 0.6  # baseline_b(bin_12_16_20_24[1,:])
    # b_20 = 0.6  # baseline_b(bin_12_16_20_24[2,:])
    # b_24 = 0.6  # baseline_b(bin_12_16_20_24[3,:])


# 生成100个2-4之间的随机长宽高组成的数据

#货箱属性类
# Car: name,length,width,height,Max_weight,position,temp_volume
class Car:
    def __init__(self,name,length,width,height,Max_weight,position,temp_volume):
        self.name = name
        self.length = length
        self.width = width
        self.height = height
        # self.weight = weight
        self.volume = length * width * height
        self.Max_weight = Max_weight
        self.position = position
        self.temp_volume = temp_volume
#货物属性类
# Bin: name,length,width,height,weight,pose
class Bin:
    def __init__(self,name,length,width,height,weight,pose,family):
        self.name = name
        self.length = length
        self.width = width
        self.height = height
        self.weight = weight
        self.volume = length * width * height
        self.pose = pose
        self.x = 0
        self.y = 0
        self.z = 0
        self.family = family #货物族名
    def get_dimension(self):
        if self.pose == Attr.Pose_wh_front:
            d = [self.length, self.width, self.height]  # 就是正面
        elif self.pose == Attr.Pose_hw_front:
            d = [self.length, self.height, self.width]
        elif self.pose == Attr.Pose_dh_front:
            d = [self.width, self.length, self.height]
        elif self.pose == Attr.Pose_hd_front:
            d = [self.width, self.height, self.length]
        elif self.pose == Attr.Pose_wd_front:
            d = [self.height, self.length, self.width]
        elif self.pose == Attr.Pose_dw_front:
            d = [self.height, self.width, self.length]
        else:
            d = []
        return d
#货物朝向类
class Attr:
    # 三个坐标轴
    Axis_x = 0
    Axis_y = 1
    Axis_z = 2
    # 原点坐标
    Position = [0, 0, 0]
    # 六个朝向
    Pose_wh_front = 0
    Pose_hw_front = 1
    Pose_hd_front = 2
    Pose_dh_front = 3
    Pose_wd_front = 4
    Pose_dw_front = 5

# 装载方式变换
class PackingMethod:
    def first_put(self):
        arg = 0
        for i in range(6):
            d = PackingMethod.set_pose(self, i).get_dimension()
            if d[Attr.Axis_x] > d[Attr.Axis_y] and d[Attr.Axis_y] > d[Attr.Axis_z]:
                arg = i
            else:
                pass
        return arg
    # 找到长是最长的 ，宽次要 高最短的那种形状填进去
    # 适合放进去的方式
    def pose_fit_arg(self, temp_L, temp_W, temp_H):  # 当前对象
        arg_ = 10000
        dv_ = 10000
        for i in range(6):
            d = PackingMethod.set_pose(self, i).get_dimension()
            #*******************************************          欧氏距离       ****************************************
            sr = math.sqrt((temp_L - d[Attr.Axis_x]) ** 2 + (temp_W - d[Attr.Axis_y]) ** 2 + (
                        temp_H - d[Attr.Axis_z]) ** 2)  # 我选择的判定方式是平方根
            if dv_ > sr:
                dv_ = sr
                arg_ = i
            else:
                continue
        return arg_
        # 返回的是 fanhuideshi

    def set_pose(self, num):
        if num >= 0 and num <= 5:
            self.pose = num
            return self
        else:
            print('数据异常')


class Sort:
    # 排序  车已经从大到小排序完了，这里车辆并没有付费，考虑到成本的话，需要加一下
    def Sort_Car(Car_list):
        Car_list.sort(key=lambda x: x.volume, reverse=True)
        return Car_list
    #货物按照体积大小排序，从小到大
    def Sort_Box(Car_list):
        Car_list.sort(key=lambda x: x.volume, reverse=False)
        return Car_list

class Packer:

    def packer_own(self,car_list_sort_fixed, box_sort_list):
        temp_l = 0    # 临时长，这是装入每个箱子的参照
        temp_w = 0
        temp_h = 0
        temp_ll = 0
        temp_ww = 0
        temp_hh = 0
        c = 0
        i_volume = 0
        b_volume = 0
        item_list = []
        peritem_list = []
        #for循环所有货箱 i:Car类
        for i in car_list_sort_fixed:
            # box_list_width = []
            # box_list_height = []
            while(True):
                # print(i.position)
                if i.position == [0,0,0]:  # 这里绝对不是i.position
                    if ((box_sort_list[0].height > i.height) or ( \
                                    box_sort_list[0].width > i.width) or ( \
                                    box_sort_list[0].length > i.length)):
                        break
                        # 这个意思就是说如果最开始就放不进去就不要放了
                    elif (
                            (box_sort_list[0].height <= i.height) and (\
                                    box_sort_list[0].width <= i.width) and (\
                                            box_sort_list[0].length <= i.length)
                    ):
                        d = PackingMethod.set_pose(box_sort_list[0],
                                                   PackingMethod.first_put(box_sort_list[0])).get_dimension()
                        temp_l = d[Attr.Axis_x]  # 初代放置作为模型开始对比
                        temp_w = d[Attr.Axis_y]
                        temp_h = d[Attr.Axis_z]
                        temp_ll = temp_l
                        temp_ww = temp_w
                        temp_hh = temp_h
                        i.position[0] += d[Attr.Axis_x]    # 这里暂时相加
                        # i.position[attr.Attr.Axis_y]+=d[attr.Attr.Axis_y]
                        # i.position[attr.Attr.Axis_z]+=d[attr.Attr.Axis_z]
                        item_list.append(box_sort_list[0])
                        peritem_list.append(box_sort_list[0].volume/i.volume)
                        i_volume += box_sort_list[0].volume
                        # box_list_width.append(box_sort_list[0].width)
                        # box_list_height.append(box_sort_list[0].height)
                        c += 1
                        box_sort_list.pop(0)
                        continue
                    # 以上是空车第一次放置的时候
                else:
                    for j in box_sort_list[0:]: #原[1:]
                        temp_box = PackingMethod.set_pose(j, PackingMethod.pose_fit_arg(j, temp_l, temp_w,temp_h)).get_dimension()
                        if (temp_box[Attr.Axis_z] > (i.height - i.position[Attr.Axis_z])) or (temp_box[Attr.Axis_y] > (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] <= (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]) and \
                                    temp_box[Attr.Axis_z] >(i.width-i.position[2]-temp_hh)):
                            temp_l = 0
                            temp_w = 0
                            temp_h = 0
                            temp_ll = 0
                            temp_hh = 0
                            temp_ww = 0
                            i.position[Attr.Axis_x] = 0
                            i.position[Attr.Axis_y] = 0
                            i.position[Attr.Axis_z] = 0
                            break
                            # 这句话意思即是后来的箱子已经放不进去了，换句话说就是已经装满了,然后变量全部归零
                        else:
                            if temp_box[Attr.Axis_y] <= (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] <= ( i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]):
                                i.position[0] += temp_box[Attr.Axis_x]
                                # print("7")
                                # global temp_ll, temp_ww, temp_hh
                                temp_ll = max(temp_ll, temp_box[Attr.Axis_x])  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = max(temp_ww, temp_box[Attr.Axis_y])
                                temp_hh = max(temp_hh, temp_box[Attr.Axis_z])
                                item_list.append(j)
                                peritem_list.append(j.volume/i.volume)
                                i_volume += j.volume
                                box_sort_list.pop(0)
                                c += 1
                                Done = False
                                continue
                                # 都小于的时候，每一个块的长度相加 ，宽度 ，高度进行记录
                            elif temp_box[Attr.Axis_y] <= (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] > (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]):
                                i.position[0] = 0
                                i.position[0] += temp_box[Attr.Axis_x]
                                i.position[1] += temp_ww
                                temp_ll = temp_box[Attr.Axis_x]  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = temp_box[Attr.Axis_y]
                                temp_hh = max(temp_hh, temp_box[Attr.Axis_z])
                                item_list.append(j)
                                peritem_list.append(j.volume/i.volume)
                                i_volume += j.volume
                                box_sort_list.pop(0)
                                c += 1
                                continue
                                # 换到下一行，x重新置为0，将当前的最大W加上

                            elif temp_box[Attr.Axis_y] > (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] <= (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]) and \
                                    temp_box[Attr.Axis_z] <=(i.width-i.position[2]-temp_hh):
                                i.position[2] += temp_hh
                                i.position[0] = temp_box[Attr.Axis_x]
                                i.position[1] = temp_box[Attr.Axis_y]
                                temp_ll = temp_box[Attr.Axis_x]  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = temp_box[Attr.Axis_y]
                                temp_hh = temp_box[Attr.Axis_z]
                                item_list.append(j)
                                peritem_list.append(j.volume/i.volume)
                                i_volume += j.volume
                                box_sort_list.pop(0)
                                c += 1
                                continue
                            elif temp_box[Attr.Axis_y] > (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] > (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]):
                                i.position[2] += temp_hh
                                i.position[0] = temp_box[Attr.Axis_x]
                                i.position[1] = temp_box[Attr.Axis_y]
                                temp_ll = temp_box[Attr.Axis_x]  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = temp_box[Attr.Axis_y]
                                temp_hh = temp_box[Attr.Axis_z]
                                item_list.append(j)
                                peritem_list.append(j.volume/i.volume)
                                i_volume += j.volume
                                box_sort_list.pop(0)
                                c += 1
                                continue
                break
            b_volume = i.volume
        return i_volume / b_volume , c , item_list, peritem_list

    def packer_oneCar_cube(self, car_list_sort_fixed, box_sort_list):
        temp_l = 0  # 临时长，这是装入每个箱子的参照
        temp_w = 0
        temp_h = 0
        temp_ll = 0
        temp_ww = 0
        temp_hh = 0
        c = 0
        i_volume = 0
        b_volume = 0
        item_list = []
        peritem_list = []
        cubes = []
        x_ = car_list_sort_fixed[0].length
        y_ = car_list_sort_fixed[0].width
        z_ = car_list_sort_fixed[0].height

        x, y, z = np.indices((x_, y_, z_)) #x,y,z type:ndarry

        # for循环所有货箱 i:Car类
        for i in car_list_sort_fixed:
            # box_list_width = []
            # box_list_height = []
            while (True):
                # print(i.position)
                if i.position == [0, 0, 0]:  # 这里绝对不是i.position
                    if ((box_sort_list[0].height > i.height) or ( \
                                    box_sort_list[0].width > i.width) or ( \
                                    box_sort_list[0].length > i.length)):
                        break
                        # 这个意思就是说如果最开始就放不进去就不要放了
                    elif (
                            (box_sort_list[0].height <= i.height) and ( \
                                    box_sort_list[0].width <= i.width) and ( \
                                            box_sort_list[0].length <= i.length)
                    ):
                        cube = (x <= box_sort_list[0].length.item()-1) & \
                               (y <= box_sort_list[0].width.item()-1) & \
                               (z <= box_sort_list[0].height.item()-1)
                        cubes.append(cube)
                        d = PackingMethod.set_pose(box_sort_list[0],
                                                   PackingMethod.first_put(box_sort_list[0])).get_dimension()
                        temp_l = d[Attr.Axis_x]  # 初代放置作为模型开始对比
                        temp_w = d[Attr.Axis_y]
                        temp_h = d[Attr.Axis_z]
                        temp_ll = temp_l
                        temp_ww = temp_w
                        temp_hh = temp_h
                        i.position[0] += d[Attr.Axis_x]  # 这里暂时相加
                        # i.position[attr.Attr.Axis_y]+=d[attr.Attr.Axis_y]
                        # i.position[attr.Attr.Axis_z]+=d[attr.Attr.Axis_z]
                        item_list.append(box_sort_list[0])
                        peritem_list.append(box_sort_list[0].volume / i.volume)
                        i_volume += box_sort_list[0].volume
                        # box_list_width.append(box_sort_list[0].width)
                        # box_list_height.append(box_sort_list[0].height)
                        c += 1
                        box_sort_list.pop(0)
                        continue
                    # 以上是空车第一次放置的时候
                else:
                    for j in box_sort_list[0:]:  # 原[1:]
                        temp_box = PackingMethod.set_pose(j, PackingMethod.pose_fit_arg(j, temp_l, temp_w,
                                                                                        temp_h)).get_dimension()
                        if (temp_box[Attr.Axis_z] > (i.height - i.position[Attr.Axis_z])) or (
                                temp_box[Attr.Axis_y] > (i.width - i.position[1]) and \
                                temp_box[Attr.Axis_x] <= (i.length - i.position[0]) and \
                                temp_box[Attr.Axis_z] <= (i.height - i.position[2]) and \
                                temp_box[Attr.Axis_z] > (i.width - i.position[2] - temp_hh)):
                            temp_l = 0
                            temp_w = 0
                            temp_h = 0
                            temp_ll = 0
                            temp_hh = 0
                            temp_ww = 0
                            i.position[Attr.Axis_x] = 0
                            i.position[Attr.Axis_y] = 0
                            i.position[Attr.Axis_z] = 0
                            break
                            # 这句话意思即是后来的箱子已经放不进去了，换句话说就是已经装满了,然后变量全部归零
                        else:
                            if temp_box[Attr.Axis_y] <= (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] <= (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]):
                                #放置货物在货箱中的位置
                                c = i.position[0]
                                #print(type(x), int(i.position[0] + temp_box[Attr.Axis_x].item()))

                                cube = (x <= int(i.position[0] + temp_box[Attr.Axis_x].item())-1) & (x >= int(i.position[0])) &\
                                    (y <= int(i.position[1] + temp_box[Attr.Axis_y].item())-1) & (y >= int(i.position[1])) &\
                                           (z <= int(i.position[2] + temp_box[Attr.Axis_z].item())-1) & (z >= int(i.position[2]))
                                cubes.append(cube)

                                #更新装箱层数
                                i.position[0] += temp_box[Attr.Axis_x]
                                # print("7")
                                # global temp_ll, temp_ww, temp_hh
                                temp_ll = max(temp_ll, temp_box[Attr.Axis_x])  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = max(temp_ww, temp_box[Attr.Axis_y])
                                temp_hh = max(temp_hh, temp_box[Attr.Axis_z])
                                item_list.append(j)
                                peritem_list.append(j.volume / i.volume)
                                i_volume += j.volume

                                box_sort_list.pop(0)
                                c += 1
                                Done = False
                                continue
                                # 都小于的时候，每一个块的长度相加 ，宽度 ，高度进行记录
                            elif temp_box[Attr.Axis_y] <= (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] > (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]):

                                #更新装箱层数
                                i.position[0] = 0
                                i.position[0] += temp_box[Attr.Axis_x]
                                i.position[1] += temp_ww
                                temp_ll = temp_box[Attr.Axis_x]  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = temp_box[Attr.Axis_y]
                                temp_hh = max(temp_hh, temp_box[Attr.Axis_z])
                                #放置货物在货箱中的位置
                                cube = (x >= int(i.position[0] - temp_box[Attr.Axis_x].item())) & (x <= int(i.position[0])-1) & \
                                    (y <= int(i.position[1] + temp_box[Attr.Axis_y].item())-1) & (y >= int(i.position[1])) & \
                                           (z <= int(i.position[2] + temp_box[Attr.Axis_z].item())-1) & (z >= int(i.position[2]))
                                cubes.append(cube)
                                item_list.append(j)
                                peritem_list.append(j.volume / i.volume)
                                i_volume += j.volume
                                box_sort_list.pop(0)
                                c += 1
                                continue
                                # 换到下一行，x重新置为0，将当前的最大W加上

                            elif temp_box[Attr.Axis_y] > (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] <= (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]) and \
                                    temp_box[Attr.Axis_z] <= (i.width - i.position[2] - temp_hh):
                                #更新装箱层数
                                i.position[2] += temp_hh
                                i.position[0] = temp_box[Attr.Axis_x]
                                i.position[1] = 0#temp_box[Attr.Axis_y]  ####
                                temp_ll = temp_box[Attr.Axis_x]  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = temp_box[Attr.Axis_y]
                                temp_hh = temp_box[Attr.Axis_z]
                                #放置货物在货箱中的位置

                                cube = (x >= int(i.position[0] - temp_box[Attr.Axis_x].item())) & (x <= int(i.position[0])-1) & \
                                    (y <= int(i.position[1] + temp_box[Attr.Axis_y].item())-1) & (y >= int(i.position[1])) & \
                                           (z >= int(i.position[2] - temp_box[Attr.Axis_z])) & (z <= int(i.position[2])-1)
                                cubes.append(cube)
                                item_list.append(j)
                                peritem_list.append(j.volume / i.volume)
                                i_volume += j.volume
                                box_sort_list.pop(0)
                                c += 1
                                continue
                            elif temp_box[Attr.Axis_y] > (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] > (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]):
                                #更新装箱层数
                                i.position[2] += temp_hh
                                i.position[0] = temp_box[Attr.Axis_x]
                                i.position[1] = 0#temp_box[Attr.Axis_y]#####
                                temp_ll = temp_box[Attr.Axis_x]  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = temp_box[Attr.Axis_y]
                                temp_hh = temp_box[Attr.Axis_z]
                                #放置货物在货箱中的位置
                                cube = (x >= int(i.position[0] - temp_box[Attr.Axis_x].item())) & (x <= int(i.position[0])-1 ) & \
                                    (y <= int(i.position[1] + temp_box[Attr.Axis_y].item())-1) & (y >= int(i.position[1])) & \
                                           (z >= int(i.position[2] - temp_box[Attr.Axis_z].item())) & (z <= int(i.position[2])-1)
                                cubes.append(cube)
                                item_list.append(j)
                                peritem_list.append(j.volume / i.volume)
                                i_volume += j.volume
                                box_sort_list.pop(0)
                                c += 1
                                continue

                break
            b_volume = i.volume
        return i_volume / b_volume, c, item_list, cubes
    def packer_oneCar_cube_family(self, car_list_sort_fixed, box_sort_list):
        temp_l = 0  # 临时长，这是装入每个箱子的参照
        temp_w = 0
        temp_h = 0
        temp_ll = 0
        temp_ww = 0
        temp_hh = 0
        c = 0
        i_volume = 0
        b_volume = 0
        item_list = []
        peritem_list = []
        cubes = []
        family = []  #family
        x_ = car_list_sort_fixed[0].length
        y_ = car_list_sort_fixed[0].width
        z_ = car_list_sort_fixed[0].height

        x, y, z = np.indices((x_, y_, z_)) #x,y,z type:ndarry

        # for循环所有货箱 i:Car类
        for i in car_list_sort_fixed:
            # box_list_width = []
            # box_list_height = []
            while (True):
                # print(i.position)
                if i.position == [0, 0, 0]:  # 这里绝对不是i.position
                    if ((box_sort_list[0].height > i.height) or ( \
                                    box_sort_list[0].width > i.width) or ( \
                                    box_sort_list[0].length > i.length)):
                        break
                        # 这个意思就是说如果最开始就放不进去就不要放了
                    elif (
                            (box_sort_list[0].height <= i.height) and ( \
                                    box_sort_list[0].width <= i.width) and ( \
                                            box_sort_list[0].length <= i.length)
                    ):
                        cube = (x <= box_sort_list[0].length.item()-1) & \
                               (y <= box_sort_list[0].width.item()-1) & \
                               (z <= box_sort_list[0].height.item()-1)
                        cubes.append(cube)
                        d = PackingMethod.set_pose(box_sort_list[0],
                                                   PackingMethod.first_put(box_sort_list[0])).get_dimension()
                        temp_l = d[Attr.Axis_x]  # 初代放置作为模型开始对比
                        temp_w = d[Attr.Axis_y]
                        temp_h = d[Attr.Axis_z]
                        temp_ll = temp_l
                        temp_ww = temp_w
                        temp_hh = temp_h
                        i.position[0] += d[Attr.Axis_x]  # 这里暂时相加
                        # i.position[attr.Attr.Axis_y]+=d[attr.Attr.Axis_y]
                        # i.position[attr.Attr.Axis_z]+=d[attr.Attr.Axis_z]
                        item_list.append(box_sort_list[0])
                        family.append(box_sort_list[0].family)

                        peritem_list.append(box_sort_list[0].volume / i.volume)
                        i_volume += box_sort_list[0].volume
                        # box_list_width.append(box_sort_list[0].width)
                        # box_list_height.append(box_sort_list[0].height)
                        c += 1
                        box_sort_list.pop(0)
                        continue
                    # 以上是空车第一次放置的时候
                else:
                    for j in box_sort_list[0:]:  # 原[1:]
                        temp_box = PackingMethod.set_pose(j, PackingMethod.pose_fit_arg(j, temp_l, temp_w,
                                                                                        temp_h)).get_dimension()
                        if (temp_box[Attr.Axis_z] > (i.height - i.position[Attr.Axis_z])) or (
                                temp_box[Attr.Axis_y] > (i.width - i.position[1]) and \
                                temp_box[Attr.Axis_x] <= (i.length - i.position[0]) and \
                                temp_box[Attr.Axis_z] <= (i.height - i.position[2]) and \
                                temp_box[Attr.Axis_z] > (i.width - i.position[2] - temp_hh)):
                            temp_l = 0
                            temp_w = 0
                            temp_h = 0
                            temp_ll = 0
                            temp_hh = 0
                            temp_ww = 0
                            i.position[Attr.Axis_x] = 0
                            i.position[Attr.Axis_y] = 0
                            i.position[Attr.Axis_z] = 0
                            break
                            # 这句话意思即是后来的箱子已经放不进去了，换句话说就是已经装满了,然后变量全部归零
                        else:
                            if temp_box[Attr.Axis_y] <= (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] <= (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]):
                                #放置货物在货箱中的位置
                                c = i.position[0]
                                #print(type(x), int(i.position[0] + temp_box[Attr.Axis_x].item()))

                                cube = (x <= int(i.position[0] + temp_box[Attr.Axis_x].item())-1) & (x >= int(i.position[0])) &\
                                    (y <= int(i.position[1] + temp_box[Attr.Axis_y].item())-1) & (y >= int(i.position[1])) &\
                                           (z <= int(i.position[2] + temp_box[Attr.Axis_z].item())-1) & (z >= int(i.position[2]))
                                cubes.append(cube)

                                #更新装箱层数
                                i.position[0] += temp_box[Attr.Axis_x]
                                # print("7")
                                # global temp_ll, temp_ww, temp_hh
                                temp_ll = max(temp_ll, temp_box[Attr.Axis_x])  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = max(temp_ww, temp_box[Attr.Axis_y])
                                temp_hh = max(temp_hh, temp_box[Attr.Axis_z])
                                item_list.append(j)
                                family.append(box_sort_list[0].family)
                                peritem_list.append(j.volume / i.volume)
                                i_volume += j.volume

                                box_sort_list.pop(0)
                                c += 1
                                Done = False
                                continue
                                # 都小于的时候，每一个块的长度相加 ，宽度 ，高度进行记录
                            elif temp_box[Attr.Axis_y] <= (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] > (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]):

                                #更新装箱层数
                                i.position[0] = 0
                                i.position[0] += temp_box[Attr.Axis_x]
                                i.position[1] += temp_ww
                                temp_ll = temp_box[Attr.Axis_x]  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = temp_box[Attr.Axis_y]
                                temp_hh = max(temp_hh, temp_box[Attr.Axis_z])
                                #放置货物在货箱中的位置
                                cube = (x >= int(i.position[0] - temp_box[Attr.Axis_x].item())) & (x <= int(i.position[0])-1) & \
                                    (y <= int(i.position[1] + temp_box[Attr.Axis_y].item())-1) & (y >= int(i.position[1])) & \
                                           (z <= int(i.position[2] + temp_box[Attr.Axis_z].item())-1) & (z >= int(i.position[2]))
                                cubes.append(cube)
                                item_list.append(j)
                                family.append(box_sort_list[0].family)
                                peritem_list.append(j.volume / i.volume)
                                i_volume += j.volume
                                box_sort_list.pop(0)
                                c += 1
                                continue
                                # 换到下一行，x重新置为0，将当前的最大W加上

                            elif temp_box[Attr.Axis_y] > (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] <= (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]) and \
                                    temp_box[Attr.Axis_z] <= (i.width - i.position[2] - temp_hh):
                                #更新装箱层数
                                i.position[2] += temp_hh
                                i.position[0] = temp_box[Attr.Axis_x]
                                i.position[1] = 0#temp_box[Attr.Axis_y]  ####
                                temp_ll = temp_box[Attr.Axis_x]  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = temp_box[Attr.Axis_y]
                                temp_hh = temp_box[Attr.Axis_z]
                                #放置货物在货箱中的位置

                                cube = (x >= int(i.position[0] - temp_box[Attr.Axis_x].item())) & (x <= int(i.position[0])-1) & \
                                    (y <= int(i.position[1] + temp_box[Attr.Axis_y].item())-1) & (y >= int(i.position[1])) & \
                                           (z >= int(i.position[2] - temp_box[Attr.Axis_z])) & (z <= int(i.position[2])-1)
                                cubes.append(cube)
                                item_list.append(j)
                                family.append(box_sort_list[0].family)
                                peritem_list.append(j.volume / i.volume)
                                i_volume += j.volume
                                box_sort_list.pop(0)
                                c += 1
                                continue
                            elif temp_box[Attr.Axis_y] > (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] > (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]):
                                #更新装箱层数
                                i.position[2] += temp_hh
                                i.position[0] = temp_box[Attr.Axis_x]
                                i.position[1] = 0#temp_box[Attr.Axis_y]#####
                                temp_ll = temp_box[Attr.Axis_x]  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = temp_box[Attr.Axis_y]
                                temp_hh = temp_box[Attr.Axis_z]
                                #放置货物在货箱中的位置
                                cube = (x >= int(i.position[0] - temp_box[Attr.Axis_x].item())) & (x <= int(i.position[0])-1 ) & \
                                    (y <= int(i.position[1] + temp_box[Attr.Axis_y].item())-1) & (y >= int(i.position[1])) & \
                                           (z >= int(i.position[2] - temp_box[Attr.Axis_z].item())) & (z <= int(i.position[2])-1)
                                cubes.append(cube)
                                item_list.append(j)
                                family.append(box_sort_list[0].family)
                                peritem_list.append(j.volume / i.volume)
                                i_volume += j.volume
                                box_sort_list.pop(0)
                                c += 1
                                continue

                break
            b_volume = i.volume
        return i_volume / b_volume, c, item_list, cubes, family

    def packer_family(self, car_list_sort_fixed, box_sort_list):
        temp_l = 0    # 临时长，这是装入每个箱子的参照
        temp_w = 0
        temp_h = 0
        temp_ll = 0
        temp_ww = 0
        temp_hh = 0
        c = 0
        i_volume = 0
        b_volume = 0
        item_list = []
        peritem_list = []
        family_list = []
        #for循环所有货箱 i:Car类
        for i in car_list_sort_fixed:
            # box_list_width = []
            # box_list_height = []
            while(True):
                # print(i.position)
                if i.position == [0,0,0]:  # 这里绝对不是i.position
                    if ((box_sort_list[0].height > i.height) or ( \
                                    box_sort_list[0].width > i.width) or ( \
                                    box_sort_list[0].length > i.length)):
                        break
                        # 这个意思就是说如果最开始就放不进去就不要放了
                    elif (
                            (box_sort_list[0].height <= i.height) and (\
                                    box_sort_list[0].width <= i.width) and (\
                                            box_sort_list[0].length <= i.length)
                    ):
                        d = PackingMethod.set_pose(box_sort_list[0],
                                                   PackingMethod.first_put(box_sort_list[0])).get_dimension()
                        temp_l = d[Attr.Axis_x]  # 初代放置作为模型开始对比
                        temp_w = d[Attr.Axis_y]
                        temp_h = d[Attr.Axis_z]
                        temp_ll = temp_l
                        temp_ww = temp_w
                        temp_hh = temp_h
                        i.position[0] += d[Attr.Axis_x]    # 这里暂时相加
                        # i.position[attr.Attr.Axis_y]+=d[attr.Attr.Axis_y]
                        # i.position[attr.Attr.Axis_z]+=d[attr.Attr.Axis_z]
                        item_list.append(box_sort_list[0])
                        peritem_list.append(box_sort_list[0].volume/i.volume)
                        i_volume += box_sort_list[0].volume
                        # box_list_width.append(box_sort_list[0].width)
                        # box_list_height.append(box_sort_list[0].height)
                        c += 1
                        family_list.append(box_sort_list[0].family)
                        box_sort_list.pop(0)
                        continue
                    # 以上是空车第一次放置的时候
                else:
                    for j in box_sort_list[0:]: #原[1:]
                        temp_box = PackingMethod.set_pose(j, PackingMethod.pose_fit_arg(j, temp_l, temp_w,temp_h)).get_dimension()
                        if (temp_box[Attr.Axis_z] > (i.height - i.position[Attr.Axis_z])) or (temp_box[Attr.Axis_y] > (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] <= (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]) and \
                                    temp_box[Attr.Axis_z] >(i.width-i.position[2]-temp_hh)):
                            temp_l = 0
                            temp_w = 0
                            temp_h = 0
                            temp_ll = 0
                            temp_hh = 0
                            temp_ww = 0
                            i.position[Attr.Axis_x] = 0
                            i.position[Attr.Axis_y] = 0
                            i.position[Attr.Axis_z] = 0
                            break
                            # 这句话意思即是后来的箱子已经放不进去了，换句话说就是已经装满了,然后变量全部归零
                        else:
                            if temp_box[Attr.Axis_y] <= (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] <= ( i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]):
                                i.position[0] += temp_box[Attr.Axis_x]
                                # print("7")
                                # global temp_ll, temp_ww, temp_hh
                                temp_ll = max(temp_ll, temp_box[Attr.Axis_x])  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = max(temp_ww, temp_box[Attr.Axis_y])
                                temp_hh = max(temp_hh, temp_box[Attr.Axis_z])
                                item_list.append(j)
                                peritem_list.append(j.volume/i.volume)
                                i_volume += j.volume
                                family_list.append(box_sort_list[0].family)
                                box_sort_list.pop(0)
                                c += 1
                                Done = False
                                continue
                                # 都小于的时候，每一个块的长度相加 ，宽度 ，高度进行记录
                            elif temp_box[Attr.Axis_y] <= (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] > (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]):
                                i.position[0] = 0
                                i.position[0] += temp_box[Attr.Axis_x]
                                i.position[1] += temp_ww
                                temp_ll = temp_box[Attr.Axis_x]  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = temp_box[Attr.Axis_y]
                                temp_hh = max(temp_hh, temp_box[Attr.Axis_z])
                                item_list.append(j)
                                peritem_list.append(j.volume/i.volume)
                                i_volume += j.volume
                                family_list.append(box_sort_list[0].family)
                                box_sort_list.pop(0)
                                c += 1
                                continue
                                # 换到下一行，x重新置为0，将当前的最大W加上

                            elif temp_box[Attr.Axis_y] > (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] <= (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]) and \
                                    temp_box[Attr.Axis_z] <=(i.width-i.position[2]-temp_hh):
                                i.position[2] += temp_hh
                                i.position[0] = temp_box[Attr.Axis_x]
                                i.position[1] = temp_box[Attr.Axis_y]
                                temp_ll = temp_box[Attr.Axis_x]  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = temp_box[Attr.Axis_y]
                                temp_hh = temp_box[Attr.Axis_z]
                                item_list.append(j)
                                peritem_list.append(j.volume/i.volume)
                                i_volume += j.volume
                                family_list.append(box_sort_list[0].family)
                                box_sort_list.pop(0)
                                c += 1
                                continue
                            elif temp_box[Attr.Axis_y] > (i.width - i.position[1]) and \
                                    temp_box[Attr.Axis_x] > (i.length - i.position[0]) and \
                                    temp_box[Attr.Axis_z] <= (i.height - i.position[2]):
                                i.position[2] += temp_hh
                                i.position[0] = temp_box[Attr.Axis_x]
                                i.position[1] = temp_box[Attr.Axis_y]
                                temp_ll = temp_box[Attr.Axis_x]  # 返回当前装箱体与之前装箱体的长宽高数据，并保留当前的最大的数值
                                temp_ww = temp_box[Attr.Axis_y]
                                temp_hh = temp_box[Attr.Axis_z]
                                item_list.append(j)
                                peritem_list.append(j.volume/i.volume)
                                i_volume += j.volume
                                family_list.append(box_sort_list[0].family)
                                box_sort_list.pop(0)
                                c += 1
                                continue
                break
            b_volume = i.volume
        return i_volume / b_volume, c, item_list, family_list
class PackerStable:
    #稳定装载，货物摆放稳定，没有悬空

    def judge_position(self):
        #判断能否装载进货箱

        return 0 #位置
    def init_height_graph(self, Car):
        #self.height_graph = torch.zeros((Car.length, Car.width))
        self.height_graph = torch.zeros((Car.length, Car.width))

    def update_height_graph(self, item, state):
        # 根据货物属性和当前高度图更新高度图
        new_state = state.clone()
        le = int(item.x)
        ri = int(item.x+item.length)
        up = int(item.y)
        do = int(item.y+item.width)
        max_h = torch.max(new_state[le:ri, up:do])
        max_h = torch.max(max_h, torch.as_tensor(item.z + item.height))
        new_state[le:ri, up:do] = max_h.clone()
        return new_state

    def check_bin(self, goods, state):
        #货箱的长宽高
        Length = self.length
        Width = self.width
        Height = self.height

        # 判断货物本身是否不能放入货箱
        if goods.length > Length or goods.width > Width or goods.height > Height:
            return -1
        # 判断假如货物放入后是否不能超出货箱范围
        elif goods.x + goods.length < 0 or goods.y + goods.width > Width or goods.height + state[goods.x][
            goods.y] > Height or goods.x + goods.length > Length:
            return -1
        else:
            qwe = 0
            for i in range(int(goods.x), int(goods.x + goods.length)):
                if qwe == 1:
                    break
                for j in range(int(goods.y), int(goods.y + goods.width)):
                    if state[i][j] > goods.z or goods.height + state[i][j] > Height:
                        return -1

        # 判断货物是否放置的稳定
        point_left_up_1 = goods.x
        point_left_up_2 = goods.y
        point_left_down_1 = goods.x + goods.length
        point_left_down_2 = point_left_up_2
        point_right_up_1 = point_left_up_1
        point_right_up_2 = point_left_up_2 + goods.width
        point_right_down_1 = point_right_up_1 + goods.length
        point_right_down_2 = point_right_up_2
        if point_right_down_2 < 0 or point_right_down_1 < 0:
            return -1
        if point_right_up_2 > Width or point_left_down_1 < 0:
            return -1
        # 计算货物底部被支持的区域面积
        max = goods.z
        sums = 0.0
        # 寻找放置区域内支撑位置个数
        for i in range(int(point_left_up_1), int(point_left_down_1)):
            for j in range(int(point_left_up_2), int(point_right_up_2)):
                if state[i][j] == max:
                    sums = sums + 1
        k = sums  # 统计当前区域内最高的格子个数
        area = k / (1.0 * (int(point_left_down_1) - int(point_left_up_1)) * (
                    int(point_right_up_2) - int(point_left_up_2)))
        # 获取有几个顶点的高度相同;
        if int(point_left_down_1) >= Length:
            point_left_down_1 = point_left_down_1 - 1
        if int(point_left_down_2) >= Width:
            point_left_down_2 = point_left_down_2 - 1
        if int(point_right_up_1) >= Length:
            point_right_up_1 = point_right_up_1 - 1
        if int(point_left_up_2) >= Width:
            point_left_up_2 = point_left_up_2 - 1
        if int(point_right_up_2) >= Width:
            point_right_up_2 = point_right_up_2 - 1
        if int(point_left_up_1) >= Length:
            point_left_up_1 = point_left_up_1 - 1
        if int(point_right_down_1) >= Length:
            point_right_down_1 = point_right_down_1 - 1
        if int(point_right_down_2) >= Width:
            point_right_down_2 = point_right_down_2 - 1
        heigh_list = []
        heigh_list.append(state[int(point_left_down_1)][int(point_left_down_2)])
        heigh_list.append(state[int(point_right_down_1)][int(point_right_down_2)])
        heigh_list.append(state[int(point_right_up_1)][int(point_right_up_2)])
        heigh_list.append(state[int(point_left_up_1)][int(point_left_up_2)])
        number = np.bincount(heigh_list)
        sum = np.max(number)
        # 判断能否被支持，可以返回1，不能则返回-1
        if sum == 3:
            if area > 0.55:
                return 1
            else:
                return -1
        elif sum == 4:
            if area > 0.4:
                return 1
            else:
                return -1
        else:
            if area > 0.6:
                return 1
            else:
                return -1

    def check_bin_below_max_z(self, goods, state, max_z):
        #货箱的长宽高
        Length = self.length
        Width = self.width
        Height = self.height
        #判断是否超过自限定最大高
        if goods.height + goods.z >max_z:
            return -1
        # 判断货物本身是否不能放入货箱
        if goods.length > Length or goods.width > Width or goods.height > Height:
            return -1
        # 判断假如货物放入后是否不能超出货箱范围
        elif goods.x + goods.length < 0 or goods.y + goods.width > Width or goods.height + state[goods.x][
            goods.y] > Height or goods.x + goods.length > Length:
            return -1
        else:
            qwe = 0
            for i in range(int(goods.x), int(goods.x + goods.length)):
                if qwe == 1:
                    break
                for j in range(int(goods.y), int(goods.y + goods.width)):
                    if state[i][j] > goods.z or goods.height + state[i][j] > Height:
                        return -1

        # 判断货物是否放置的稳定
        point_left_up_1 = goods.x
        point_left_up_2 = goods.y
        point_left_down_1 = goods.x + goods.length
        point_left_down_2 = point_left_up_2
        point_right_up_1 = point_left_up_1
        point_right_up_2 = point_left_up_2 + goods.width
        point_right_down_1 = point_right_up_1 + goods.length
        point_right_down_2 = point_right_up_2
        if point_right_down_2 < 0 or point_right_down_1 < 0:
            return -1
        if point_right_up_2 > Width or point_left_down_1 < 0:
            return -1
        # 计算货物底部被支持的区域面积
        max = goods.z
        sums = 0.0
        # 寻找放置区域内支撑位置个数
        for i in range(int(point_left_up_1), int(point_left_down_1)):
            for j in range(int(point_left_up_2), int(point_right_up_2)):
                if state[i][j] == max:
                    sums = sums + 1
        k = sums  # 统计当前区域内最高的格子个数
        area = k / (1.0 * (int(point_left_down_1) - int(point_left_up_1)) * (
                    int(point_right_up_2) - int(point_left_up_2)))
        # 获取有几个顶点的高度相同;
        if int(point_left_down_1) >= Length:
            point_left_down_1 = point_left_down_1 - 1
        if int(point_left_down_2) >= Width:
            point_left_down_2 = point_left_down_2 - 1
        if int(point_right_up_1) >= Length:
            point_right_up_1 = point_right_up_1 - 1
        if int(point_left_up_2) >= Width:
            point_left_up_2 = point_left_up_2 - 1
        if int(point_right_up_2) >= Width:
            point_right_up_2 = point_right_up_2 - 1
        if int(point_left_up_1) >= Length:
            point_left_up_1 = point_left_up_1 - 1
        if int(point_right_down_1) >= Length:
            point_right_down_1 = point_right_down_1 - 1
        if int(point_right_down_2) >= Width:
            point_right_down_2 = point_right_down_2 - 1
        heigh_list = []
        heigh_list.append(state[int(point_left_down_1)][int(point_left_down_2)])
        heigh_list.append(state[int(point_right_down_1)][int(point_right_down_2)])
        heigh_list.append(state[int(point_right_up_1)][int(point_right_up_2)])
        heigh_list.append(state[int(point_left_up_1)][int(point_left_up_2)])
        number = np.bincount(heigh_list)
        sum = np.max(number)
        # 判断能否被支持，可以返回1，不能则返回-1
        if sum == 3:
            if area > 0.55:
                return 1
            else:
                return -1
        elif sum == 4:
            if area > 0.4:
                return 1
            else:
                return -1
        else:
            if area > 0.6:
                return 1
            else:
                return -1

    #获取货物x,y坐标，二维角度
    def idx_to_position(self, idx):
        # 取整除 - 返回商的整数部分（向下取整）
        x = torch.div(idx, self.width, rounding_mode='trunc')
        y = idx % self.width
        return int(x), int(y)

    def packer_family_stable_2(self, car_list_sort_fixed, box_sort_list):
        #取消可装载点时取消循环或者递归
        #family:类别记录
        #具有稳定性的放置
        temp_l = 0    # 临时长，这是装入每个箱子的参照
        temp_w = 0
        temp_h = 0
        temp_ll = 0
        temp_ww = 0
        temp_hh = 0
        c = 0
        i_volume = 0
        b_volume = 0
        item_list = []
        peritem_list = []
        family_list = []
        self.init_height_graph(car_list_sort_fixed[0])
        #for循环所有货箱 i:Car类
        for i in car_list_sort_fixed:
            self.width = i.width
            self.height = i.height
            self.length = i.length
            #_break_1 = True
            max_z = 0
            for kkk in range(2):
                if i.position == [0, 0, 0]:  # 这里绝对不是i.position
                    if ((box_sort_list[0].height > i.height) or (\
                                    box_sort_list[0].width > i.width) or ( \
                                    box_sort_list[0].length > i.length)):
                        break
                        # 这个意思就是说如果最开始就放不进去就不要放了
                    elif (
                            (box_sort_list[0].height <= i.height) and (\
                                    box_sort_list[0].width <= i.width) and (\
                                            box_sort_list[0].length <= i.length)
                    ):
                        first_item = box_sort_list[0]
                        # first_item.length = d[Attr.Axis_x]
                        # first_item.width = d[Attr.Axis_y]
                        # first_item.height = d[Attr.Axis_z]
                        #print(first_item.length, first_item.width, first_item.height)
                        first_item.x, first_item.y, first_item.z = 0, 0, 0
                        i.position = [first_item.length, first_item.width, first_item.height]
                        #更新高度图
                        self.height_graph = self.update_height_graph(first_item, self.height_graph)
                        #可行性掩码的最大高度限制
                        max_z = first_item.height
                        #删除内存
                        item_list.append(box_sort_list[0])
                        peritem_list.append(box_sort_list[0].volume/i.volume)
                        i_volume += box_sort_list[0].volume
                        c += 1
                        family_list.append(box_sort_list[0].family)
                        box_sort_list.pop(0)
                        continue
                    # 以上是空车第一次放置的时候
                else:
                    _break = False
                    for j in box_sort_list[0:]: #原[1:]
                        temp_box = PackingMethod.set_pose(j, PackingMethod.pose_fit_arg(j, temp_l, temp_w,temp_h)).get_dimension()
                        item = j
                        item.length = temp_box[Attr.Axis_x]
                        item.width = temp_box[Attr.Axis_y]
                        item.height = temp_box[Attr.Axis_z]
                        #获取货物的可行掩码矩阵
                        real_mask = self.real_mask_below_max_z(self.height_graph, item, max_z)
                        #print(real_mask)
                        if torch.sum(real_mask) != 0. :
                            #取可行性掩码中第一个为1的位置作为放置点
                            position_xyz = torch.argmax(real_mask)
                            item.x, item.y = self.idx_to_position(position_xyz)
                            item.z = self.height_graph[item.x, item.y]
                            self.height_graph = self.update_height_graph(item, self.height_graph)
                            max_z = torch.max(max_z, item.z + item.height)
                        elif torch.sum(real_mask) == 0.:
                            #挑出循环体
                            _break = True
                            print("装载满了！！")
                            break
                        # if _break:
                        #     break
            b_volume = i.volume
        return i_volume / b_volume, c, item_list, family_list

    def real_mask(self, state, item):
        truth_mask = torch.zeros([self.length, self.width], dtype=torch.uint8)
        #predict_mask_length = predict_mask.shape[1]
        lx = int(item.length.item())
        ly = int(item.width.item())
        lz = int(item.height.item())
        #jund_0001 = torch.tensor(0.001)
        #jund_0 = torch.tensor(0.0)
        for i in range(self.width * self.length):
            action_x, action_y = self.idx_to_position(i)
            #mask_item = predict_mask[0, i]
            # 货箱放置的x,y缺一个z
            # 要根据state判断这个点能不能装进去这个货物
            #name,length,width,height,weight,pose,family
            item = Bin("", lx, ly, lz, 0, 0, 0)
            item.x = action_x
            item.y = action_y
            item.z = self.height_graph[action_x, action_y]
            if self.check_bin(item, state) != -1:
                truth_mask[action_x, action_y] = 1
        return truth_mask
    def real_mask_below_max_z(self, state, item, max_z):
        #在最大z的限制之下，确定可行性掩码
        truth_mask = torch.zeros([self.length, self.width], dtype=torch.uint8)
        #predict_mask_length = predict_mask.shape[1]
        lx = int(item.length.item())
        ly = int(item.width.item())
        lz = int(item.height.item())
        #jund_0001 = torch.tensor(0.001)
        #jund_0 = torch.tensor(0.0)
        for i in range(self.width * self.length):
            action_x, action_y = self.idx_to_position(i)
            #mask_item = predict_mask[0, i]
            # 货箱放置的x,y缺一个z
            # 要根据state判断这个点能不能装进去这个货物
            #name,length,width,height,weight,pose,family
            item = Bin("", lx, ly, lz, 0, 0, 0)
            item.x = action_x
            item.y = action_y
            item.z = self.height_graph[action_x, action_y]
            if self.check_bin_below_max_z(item, state, max_z) != -1:
                truth_mask[action_x, action_y] = 1
        return truth_mask

class Bin_env:
    def __init__(self, items, prob, index,
                 carlist):  # param:items:itemlist:data_create()的列表, problist, indexlist, carlist
        self.Reward_list = []
        self.Index_list = []
        self.State_list = []
        self.prob_list = []
        self.peritem_list = []
        self.carlist = carlist
        load_items = Creator.bin_create(items, index)  # 装箱
        # rate 占有率
        # num:
        # item_list
        #
        rate, num, item_list, peritem_list = Packer().packer_own(carlist, load_items)
        for z in item_list:
            self.Reward_list.append(z.volume)
        for x in range(len(item_list)):
            self.State_list.append(x)
            self.Index_list.append(index[x][0])
            self.prob_list.append(prob[x][0])
        self.peritem_list = peritem_list
        # print(peritem_list)

    # 定义方法：
    # 作用： 返回当前状态的利用率
    def render(self, state):
        pass
    def reset(self):
        pass

    def step(self, state):  # 这个动作就是当前的序列
        pass